package com.gopay.common.cps.dao.trans.impl;

import com.gopay.common.PageInfo;
import com.gopay.common.base.dao.impl.BaseDAOImpl;
import com.gopay.common.constants.trans.TxnStaCode;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.cps.dao.trans.PartAcctOrderQueryDAO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 分账订单查询DAO实现
 * @author yu_liu6@hnair.com
 * @date 2018-03-06 13:39:38
 */
@Repository("partAcctOrderQueryDAO")
public class PartAcctOrderQueryDAOImpl extends BaseDAOImpl<Object[], Serializable>
                                    implements PartAcctOrderQueryDAO{
    private static final String SQL_LIST_ORDERS_PRI = "select DISTINCT m.GOPAY_TXN_TM, m.ORDER_STLM_TIME, m.TRAN_FINISH_TIME, " +
            "info.CUST_NAME, m.MAIN_RECV_ACCT, m.GOPAY_ORDER_ID, m.GOPAY_INT_TXN_CD, res.MER_TXN_AMT as resourceAmt, " +
            "m.MER_TXN_AMT as orderAmt, m.TXN_STA_CD, recv.OTHER_RECV_STATUS, force.IS_FORCE_RECV, " +
            "m.RELEVANCE_GOPAY_ORDER_ID, res.GOPAY_INT_TXN_CD as resIntTxnCd, nvl(wav.STEP_NUM, -1), nvl(wav.DECISION, -1), " +
            " nvl(wav.DONE, -1), assist.OTHER_RECV_INFO, dtl.BAL_AMT  " +
            "from CPS_GEN_MAIN_ORDER m " +
            "left join CPS_GEN_MAIN_ORDER res " +
            "on res.GOPAY_ORDER_ID = m.RELEVANCE_GOPAY_ORDER_ID " +
            "left join CPS_GEN_RECEIPT_ORDER force " +
            "on force.GOPAY_ORDER_ID = res.GOPAY_ORDER_ID " +
            "left join CPS_GEN_RECEIPT_ORDER recv " +
            "on recv.GOPAY_ORDER_ID = m.GOPAY_ORDER_ID " +
            "left join CPS_GEN_ASSIST_ORDER assist " +
            "on assist.GOPAY_ORDER_ID = m.GOPAY_ORDER_ID " +
            "left join gopay_all_cust_info info " +
            "on info.CUST_ID = m.MAIN_RECV_CUST_ID " +
            "left join cps_receipt_split_dtl dtl " +
            "on dtl.SPLIT_ID = m.GOPAY_ORDER_ID " +
            " left join (select v.target_id, v.step_num, v.decision, v.done, v.task_id, " +
            "                   max(v.task_id) OVER(PARTITION BY v.target_id) maxTaskId " +
            "              from WF_APPR_VIEW v) wav on (wav.target_id = m.gopay_order_id and " +
            "                                wav.task_id >= wav.maxTaskId) " +
            "where m.GOPAY_INT_TXN_CD in (:transType) ";

//    private static final String SQL_NO_ORDER_PART_ACCT = " union all " +
//            "select part.CREATE_TS as GOPAY_TXN_TM, null as ORDER_STLM_TIME, null as TRAN_FINISH_TIME, " +
//            "info.CUST_NAME, part.SPLIT_ACCT as MAIN_RECV_ACCT, part.SPLIT_ID as GOPAY_ORDER_ID," +
//            " '00606' as GOPAY_INT_TXN_CD, part.MER_TXN_AMT as orderAmt, part.BAL_AMT as partOrderAmt, " +
//            "30000 as TXN_STA_CD, '0' as OTHER_RECV_STATUS, '0' as IS_FORCE_RECV, " +
//            "part.MIAN_GOPAY_ORDER_ID as RELEVANCE_GOPAY_ORDER_ID " +
//            "from cps_receipt_spilt_dtl part " +
//            "left join acps_acct_mast acct " +
//            "on acct.acct_id = part.split_acct " +
//            "left join gopay_all_cust_info info " +
//            "on info.cust_id = acct.cust_id " +
//            "where part.IS_CREATED = '0' ";

    /**
     * 分账订单分页查询
     * @param param 参数集合
     * @param pageInfo 分页信息
     * @return
     */
    @Override
    public PageInfo listOrdersForPage(Map<String, Object> param, PageInfo pageInfo) {
        String sql = buildSql(param);
        int count = countBySql(sql, param);
        pageInfo.setTotalCount(count);
        List<Object[]> records = findBySql(sql, param, pageInfo.getPageNum(), pageInfo.getPageSize());
        pageInfo.setData(records);
        return pageInfo;
    }

    /**
     * 分账订单查询，导出用
     * @param param
     * @return
     */
    @Override
    public List<Object[]> listOrders(Map<String, Object> param) {
        return findBySql(buildSql(param), param);
    }

    /**
     * 分账订单主键查询
     * @param gopayOrderId 订单主键
     * @return
     */
    @Override
    public Object[] findOneById(String gopayOrderId) {
        Map<String, Object> param = new HashMap<>(2);
        param.put("gopayOrderId", gopayOrderId);
        param.put("transType", new String[]{IntTxnCd._00606.value, IntTxnCd._01202.value});
        String sql = SQL_LIST_ORDERS_PRI + " and m.gopay_order_id = :gopayOrderId ";
        List<Object[]> result = findBySql(sql, param);
        return result.isEmpty() ? null : result.get(0);
    }

    private String buildSql(Map<String, Object> param){
        StringBuilder sql = new StringBuilder(SQL_LIST_ORDERS_PRI);
        //如果查询条件大于1条，并且分账状态是全部或者待分账，则需要加入分账明细表中未分账的部分
//        String partAcctStatus = (String) param.get("partAcctStatus");
//        if(StringUtils.isBlank(partAcctStatus) || "1".equals(partAcctStatus)){
//            sql.append(SQL_NO_ORDER_PART_ACCT);
//        }
//        sql.append(") t where 1=1 ");
        if(StringUtils.isNotBlank((String)param.get("custId"))){
            sql.append(" and (m.mer_id =:custId or m.pay_cust_id =:custId or m.main_recv_cust_id =:custId ) ");
        }

        if(StringUtils.isNotBlank((String)param.get("gopayTxnTmBegin"))){
            sql.append(" and m.GOPAY_TXN_TM >= to_date(:gopayTxnTmBegin, 'yyyy-mm-dd hh24:mi:ss')");
        }
        if(StringUtils.isNotBlank((String)param.get("gopayTxnTmEnd"))){
            sql.append(" and m.GOPAY_TXN_TM <= to_date(:gopayTxnTmEnd, 'yyyy-mm-dd hh24:mi:ss')");
        }
        if(StringUtils.isNotBlank((String)param.get("orderStlmTmBegin"))){
            sql.append(" and m.ORDER_STLM_TIME >= to_date(:orderStlmTmBegin, 'yyyy-mm-dd hh24:mi:ss')");
        }
        if(StringUtils.isNotBlank((String)param.get("orderStlmTmEnd"))){
            sql.append(" and m.ORDER_STLM_TIME <= to_date(:orderStlmTmEnd, 'yyyy-mm-dd hh24:mi:ss')");
        }
        if(StringUtils.isNotBlank((String)param.get("partAccountingFinishTmBegin"))){
            sql.append(" and m.TRAN_FINISH_TIME >= to_date(:partAccountingFinishTmBegin, 'yyyy-mm-dd hh24:mi:ss')");
        }
        if(StringUtils.isNotBlank((String)param.get("partAccountingFinishTmEnd"))){
            sql.append(" and m.TRAN_FINISH_TIME <= to_date(:partAccountingFinishTmEnd, 'yyyy-mm-dd hh24:mi:ss')");
        }
        if(StringUtils.isNotBlank((String) param.get("partAcctStatus"))){
            sql.append(" and recv.OTHER_RECV_STATUS = :partAcctStatus");
        }
        if(StringUtils.isNotBlank((String) param.get("txnStaCd"))){
            int txnStaCd = Integer.parseInt((String) param.get("txnStaCd"));
            if(TxnStaCode.TXN_STA_CD_20000.value == txnStaCd){
                sql.append(" and m.TXN_STA_CD = 20000 ");
            } else if(TxnStaCode.TXN_STA_CD_30000.value == txnStaCd){
                sql.append(" and m.TXN_STA_CD >= 30000 ");
            } else {
                sql.append(" and m.TXN_STA_CD between 20001 and 29999 ");
            }
            param.remove("txnStaCd");
        }
        if(StringUtils.isNotBlank((String)param.get("partAcctOrderId"))){
            sql.append(" and m.GOPAY_ORDER_ID = :partAcctOrderId");
        }
        if(StringUtils.isNotBlank((String)param.get("recvCustName"))){
            sql.append(" and info.CUST_NAME = :recvCustName");
        }
        if(StringUtils.isNotBlank((String)param.get("resourceOrderId"))){
            sql.append(" and m.RELEVANCE_GOPAY_ORDER_ID = :resourceOrderId");
        }
        if(StringUtils.isNotBlank((String)param.get("isForcePartAccounting"))){
            sql.append(" and force.IS_FORCE_RECV = :isForcePartAccounting");
        }
        if(StringUtils.isNotBlank((String)param.get("tmBegin"))){
            sql.append(" and m.CREATED_TS >= to_date(:tmBegin, 'yyyy-mm-dd hh24:mi:ss')");
        }
        if(StringUtils.isNotBlank((String)param.get("tmEnd"))){
            sql.append(" and m.CREATED_TS <= to_date(:tmEnd, 'yyyy-mm-dd hh24:mi:ss')");
        }
        /*if(null != param.get("acctIds")){
            sql.append(" and m.MAIN_RECV_ACCT in (:acctIds)");
        }*/

        sql.append(" order by m.GOPAY_TXN_TM desc ");

        return sql.toString();
    }

    private int countBySql(String resource, Map<String, Object> param){
        String sql = "select count(1) from ( " + resource + ")";
        return findCountBySql(sql, param);
    }
}
